//
//
//#include "cuda_runtime.h"
//#include "cuda_profiler_api.h"
//
//
//#include <stdlib.h>
//#include <stdio.h>
//#include "helper_timer.h"
//#include <memory>
//#include "CudaComputeContext.h"
//#include "moderngpu.cuh"
//#include "include/cudaEsg.h"
//#include "include/kernel.h"
//
//
//namespace cudaEsg {
//
//	using namespace std;
//
//
//	operation_errors_t CudaComputeContext::Ratings(int setId, int universeId, int weightMatrixId, unsigned char filter, RatingsResult &result) {
//		cudaProfilerStart();
//		cudaError_t cudaStatus;
//
//
//		cudaGetLastError(); //reset errors;
//
//		this->ResetStatistics();
//		ESGSet* set = GetSet(setId);
//
//
//		if (set == NULL) {
//			return operation_errors_t(esgSetNotFound);
//		}
//
//		if (set->companiesCount != result.companiesCount)
//			return operation_errors_t(esgComaniesCountMismatch, "");
//
//		if (set->indicatorsCount != result.indicatorsCount)
//			return operation_errors_t(esgIndicatorsCountMismatch);
//
//		if ((set->clusterGroupHeadsCount + 1) != result.clusterGroupsCount)
//			return operation_errors_t(esgClusterGroupsMismatch);
//
//
//		float *v_d = set->indicators_scores;
//		if (v_d == nullptr)
//			return operation_errors_t(esgIndicatorsScoresNotFound);
//
//
//		float *p_d = set->GetMatrix(weightMatrixId);
//		if (p_d == NULL)
//			return operation_errors_t(esgMatrixNotFound);
//
//		unsigned char  *u_d = set->GetUniverse(universeId);
//		if (u_d == NULL)
//			return operation_errors_t(esgUniverseNotFound);
//
//		unsigned char  *attributes_d = set->attributes;
//		if (attributes_d == NULL)
//			return operation_errors_t(esgAttributesNotFound);
//
//		sdkResetTimer(&_timer);
//		sdkStartTimer(&_timer);
//
//
//		int companiesNo = set->companiesCount;
//		int indicatorsNo = set->indicatorsCount;
//		mgpu::byte clustersCount = set->CLUSTERS_COUNT;
//		mgpu::byte disjunctClustersCount = set->DISJUNCT_CLUSTERS_COUNT;
//		int ratingsCount = set->CLUSTERS_COUNT * companiesNo;
//
//
//
//		try {
//			cudaError_t status;
//			_mgpuContext->Start();
//
//			status = cudaMemcpyToSymbol(esgEnds, set->h_configEgsHeads, sizeof(mgpu::byte) * set->h_configEsgHeadsCount);
//			returnOnErrorMacro(status);
//			status = cudaMemcpyToSymbol(clusterStarts, set->h_configDisjunctClustersHeads, sizeof(mgpu::byte) * set->h_configDisjunctClustersHeadsCount);
//			returnOnErrorMacro(status);
//			status = cudaMemcpyToSymbol(clusterGroups, set->h_configDisjunctClustersMap, sizeof(mgpu::byte) * set->h_configDisjunctClustersMapCount);
//
//
//			float *h_ratingsPinned;
//			cudaStatus = cudaMallocHost((void**)&h_ratingsPinned, sizeof(float)*ratingsCount);
//			returnOnErrorMacro(cudaStatus);
//			result.timedOperations->push_back(make_unique<Operation>("cudaMallocHost<h_ratings>", _mgpuContext->Split()));
//			this->AddMemoryOperation("host - h_ratingsPinned", sizeof(float)*ratingsCount);
//
//
//			int* h_companies_map;
//			cudaStatus = cudaMallocHost((void**)&h_companies_map, sizeof(int)*ratingsCount);//throws CudaException
//			result.timedOperations->push_back(make_unique<Operation>("cuda_mallocHost<h_companies_map>", _mgpuContext->Split()));
//			this->AddMemoryOperation("host - h_companies_map", sizeof(int)*ratingsCount);
//
//
//
//			float* h_indicatorsRatings;
//			float* h_reference_indicatorsRatings = nullptr;
//			if (result.options & cudaEsg::ComputeIndicatorsRatingsOption != 0){
//				cudaStatus = cudaMallocHost((void**)&h_indicatorsRatings, sizeof(float)*companiesNo * indicatorsNo);//throws CudaException
//				result.timedOperations->push_back(make_unique<Operation>("cuda_mallocHost<h_indicatorsRatings>", _mgpuContext->Split()));
//
//				h_reference_indicatorsRatings = h_indicatorsRatings;
//				this->AddMemoryOperation("host - h_indicatorsRatings", companiesNo * indicatorsNo*sizeof(float));
//			}
//
//
//
//			//int threadsPerBlock = 128;
//			//int blocksPerGrid = companiesNo / threadsPerBlock;
//			//if (companiesNo % threadsPerBlock != 0)
//			//{
//			//	++blocksPerGrid; // ensure that all companies are assigned to a thread.
//			//}
//
//			//int sharedSizeMemory;
//			//sharedSizeMemory = threadsPerBlock*(set->h_configEsgHeadsCount + 1)*sizeof(float);
//			//computeRatingsKernel << < blocksPerGrid, threadsPerBlock, sharedSizeMemory >> >(v_d, p_d, u_d, attributes_d, filter, h_ratingsPinned, h_companies_map, h_reference_indicatorsRatings, companiesNo, indicatorsNo, disjunctClustersCount, clustersCount);
//
//			computeRatings(set->h_configEsgHeadsCount + 1, v_d, p_d, u_d, attributes_d, filter, h_ratingsPinned, h_companies_map, h_reference_indicatorsRatings, companiesNo, indicatorsNo, disjunctClustersCount, clustersCount);
//
//
//			status = cudaPeekAtLastError(); //launch errors;
//			returnOnErrorMacro(status);
//			result.timedOperations->push_back(make_unique<Operation>("kernel<computeRatingsKernel>", _mgpuContext->Split()));
//
//			//throws CudaException on cudaStatus != cudaSucess (including previous kernel execution errors)
//			mgpu::SegSortPairsFromIndices(h_ratingsPinned, h_companies_map, ratingsCount, set->d_groupHeads, set->groupHeadsCount, *_mgpuContext, mgpu::greater<float>());
//
//			result.timedOperations->push_back(make_unique<Operation>("kernelSegment<sort>", _mgpuContext->Split()));
//
//			memcpy(result.ratings, h_ratingsPinned, ratingsCount*sizeof(float));
//			result.timedOperations->push_back(make_unique<Operation>("toHostMemory<d_ratings>", _mgpuContext->Split()));
//
//
//			memcpy(result.indices, h_companies_map, ratingsCount*sizeof(int));
//			result.timedOperations->push_back(make_unique<Operation>("toHostMemory<d_companies_map>", _mgpuContext->Split()));
//
//			if (result.options & ComputeIndicatorsRatingsOption != 0){
//				memcpy(result.indicators_ratings, h_indicatorsRatings, companiesNo * indicatorsNo * sizeof(float));
//				returnOnErrorMacro(status);
//				result.timedOperations->push_back(make_unique<Operation>("toHostMemory<h_indicatorsRatings>", _mgpuContext->Split()));
//			}
//
//			sdkStopTimer(&_timer);
//			float  ratingsMilliseconds = sdkGetTimerValue(&_timer);
//
//			sdkResetTimer(&_timer);
//			sdkStartTimer(&_timer);
//
//			ComputeRanking(result, h_ratingsPinned, set);
//			sdkStopTimer(&_timer);
//
//			float rankingsMilliseconds = sdkGetTimerValue(&_timer);
//			result.timedOperations->push_back(make_unique<Operation>("ranking", rankingsMilliseconds / 1000));
//
//			float totalTimeMilliseconds = ratingsMilliseconds + rankingsMilliseconds;
//			result.timedOperations->push_back(make_unique<Operation>("TotalRankingTime", totalTimeMilliseconds / 1000));
//
//
//			cudaFreeHost(h_ratingsPinned);
//			cudaFreeHost(h_companies_map);
//			cudaFreeHost(h_indicatorsRatings);
//
//		}
//		catch (MgpuArchVersionException& exception){
//			return operation_errors_t(esgCudaInvalidArch, "MgpuArchVersion: this CUDA executable was not compiled with support for current device arch");
//		}
//		catch (CudaException& exception){
//			cudaError_t status = exception.error;
//			returnOnErrorMacro(status);
//		}
//		catch (...){
//			return operation_errors_t(esgError);
//		}
//
//
//		cudaProfilerStop();
//		return operation_errors_t::success();
//
//	}
//
//	void CudaComputeContext::ComputeRanking(RatingsResult &result, float* ratings_h, ESGSet* set){
//
//		int *rankings = result.rankings;
//		float *mins = result.group_mins;
//		float *maxs = result.group_maxs;
//		float *avgs = result.group_avgs;
//		int *groupsCounts = result.group_counts;
//		int clusterGroupHeadsCount = set->clusterGroupHeadsCount;
//		int* clusterGroupHeads = set->h_clusterGroupHeads;
//
//		int companiesNo = result.companiesCount;
//
//		float * currentMin = mins;
//		float * currentMax = maxs;
//		float *currentAvg = avgs;
//		int * currentGroupCount = groupsCounts;
//		int clustersCount = set->CLUSTERS_COUNT;
//		for (int clusterIndex = 0; clusterIndex < clustersCount; clusterIndex++)
//		{
//			int baseIndex = clusterIndex * companiesNo;
//			int nextChangeIndex = 0;
//			int currentHeadIndex = -1;
//			float sum = 0;
//			int rank = 0;
//			int computedRank = 1;
//
//			*currentMin = -1;
//			*currentMax = -1;
//			*currentAvg = -1;
//
//			for (int i = 0; i <= companiesNo; i++)
//			{
//				if (i == nextChangeIndex)  //head group change
//				{
//					if (i != 0) {
//						if (rank > 0)
//							*currentAvg = sum / rank;
//						else
//							*currentAvg = -1;
//
//						*currentGroupCount = rank;
//
//						++currentAvg;
//						++currentMax;
//						++currentGroupCount;
//						++currentMin;
//
//						*currentMin = -1;
//						*currentMax = -1;
//						*currentAvg = -1;
//					}
//
//					if (i == companiesNo)
//						break;
//
//					sum = 0;
//					rank = 0;
//					computedRank = 1;
//
//					nextChangeIndex = companiesNo;
//					++currentHeadIndex;
//
//					if (currentHeadIndex < clusterGroupHeadsCount)
//					{
//						nextChangeIndex = clusterGroupHeads[currentHeadIndex];
//					}
//				}
//
//				if (i == companiesNo)
//					break;
//
//				int  currentIndex = baseIndex + i;
//				float rating = ratings_h[currentIndex];
//
//				if (rating <= -3){
//
//					rankings[currentIndex] = -1;
//					ratings_h[currentIndex] = (-1)*(rating + 4); //reverse filter transformation
//
//					continue;
//				}
//				else
//					if (rating != rating) { //NAN number
//						rankings[currentIndex] = -2;
//						continue;
//					}
//
//				++rank;
//
//				if (i == 0 || (rating != ratings_h[currentIndex - 1]))
//				{
//					computedRank = rank;
//				}
//
//				if (*currentMax == -1) {
//					*currentMax = rating;
//				}
//
//				*currentMin = rating;
//				sum += rating;
//
//
//				rankings[currentIndex] = computedRank;
//			}
//		}
//
//	}
//
//	CudaComputeContext::CudaComputeContext(){
//		try {
//			_mgpuContext = mgpu::CreateCudaDevice(0, NULL, true);
//		}
//		catch (MgpuArchVersionException& exception){
//			operation_errors_t operation = operation_errors_t(esgCudaInvalidArch, "MgpuArchVersion: this CUDA executable was not compiled with support for current device arch");
//			throw ComputeContextException(operation);
//		}
//		catch (CudaException& exception){
//			cudaError_t status = exception.error;
//			operation_errors_t operation = operation_errors_t(esgCudaError, status, cudaGetErrorString(status), "", -1, "");
//			throw ComputeContextException(operation);
//		}
//		catch (...){
//			throw ComputeContextException(operation_errors_t(esgError));
//		}
//		sets = new std::vector<std::tuple<int, ESGSet*>>();
//		memoryStatistics = new MemoryOperations();
//		sdkCreateTimer(&_timer);
//	}
//
//	CudaComputeContext::~CudaComputeContext(){
//
//		delete _timer;
//
//		delete memoryStatistics;
//		while (!sets->empty()){
//			ESGSet* set = std::get<1>(sets->back());
//			CleanSet(set);
//
//			sets->pop_back();
//			delete set;
//		}
//		delete sets;
//	}
//
//	operation_errors_t CudaComputeContext::AddSet(SetConfiguration configuration) {
//
//		size_t size;
//		cudaGetLastError(); //reset errors;
//
//		if (configuration.companiesCount <= 0 || configuration.groupsHeadsCount < 0)
//			return operation_errors_t(esgInvalidParameters);
//
//		if (configuration.groupsHeadsCount > 0 && configuration.groupsHeads == NULL)
//		{
//			return operation_errors_t(esgInvalidParameters);
//		}
//
//		if (configuration.esgHeadsCount != ESG_ENDS_COUNT)
//		{
//			return operation_errors_t(esgInvalidEsgEndsCount, "The esg cluster must have 2 HEADS");
//		}
//
//		ESGSet* set = GetSet(configuration.setId);
//
//		if (set != NULL)
//			return operation_errors_t(esgDuplicateEntity);
//
//		if (configuration.DISJUNCT_CLUSTERS_COUNT > MAX_DISJUNCT_CLUSTERS_COUNT){
//			return operation_errors_t(esgMaxDisjunctClustersCount);
//		}
//
//		if (configuration.disjunctClustersHeadsCount > MAX_DISJUNCT_CLUSTERS_HEADS){
//			return operation_errors_t(esgMaxDisjunctClustersHeads);
//		}
//
//		int CLUSTERS_COUNT = configuration.CLUSTERS_COUNT;
//
//		set = new ESGSet();
//		size = _msize(set);
//
//		this->AddMemoryOperation("host - set alloc", size);
//		set->companiesCount = configuration.companiesCount;
//
//		int* d_heads = nullptr;
//
//		operation_errors_t returnStatus = operation_errors_t::success();
//
//		for (int i = 0; i < 1; i++)
//		{
//			int* h_heads = NULL;
//
//			int repeteadHeadsCount = (configuration.groupsHeadsCount + 1) * CLUSTERS_COUNT - 1;
//
//			h_heads = (int*)malloc(repeteadHeadsCount * sizeof(int));
//
//			if (h_heads == NULL){
//				returnStatus = operation_errors_t(esgMemoryAllocationError);
//				break;
//			}
//
//			size = _msize(h_heads);
//			this->AddMemoryOperation("host - h_heads", size);
//
//			int currentIndex = 0;
//			for (int i = 0; i < CLUSTERS_COUNT; i++)
//			{
//				if (i > 0){
//					h_heads[currentIndex] = configuration.companiesCount * i;
//					++currentIndex;
//				}
//
//				for (int j = 0; j < configuration.groupsHeadsCount; j++) {
//					h_heads[currentIndex] = configuration.groupsHeads[j] + configuration.companiesCount * i;
//					++currentIndex;
//				}
//			}
//
//			cudaError_t cudaStatus = cudaMalloc((void **)&d_heads, repeteadHeadsCount * sizeof(int));
//
//
//
//			if (cudaStatus != cudaSuccess)
//			{
//				returnStatus = getOperationErrorFromCudaStatusMacro(cudaStatus);
//				break;
//			}
//
//			cudaStatus = cudaMemcpy(d_heads, h_heads, repeteadHeadsCount* sizeof(int), cudaMemcpyHostToDevice);
//			free(h_heads);
//			if (cudaStatus != cudaSuccess)
//			{
//				returnStatus = getOperationErrorFromCudaStatusMacro(cudaStatus);;
//				break;
//			}
//
//			set->groupHeadsCount = repeteadHeadsCount;
//			set->d_groupHeads = d_heads;
//			if (configuration.groupsHeads != NULL) {
//				set->h_clusterGroupHeads = (int*)malloc(sizeof(int) * configuration.groupsHeadsCount);
//				memcpy(set->h_clusterGroupHeads, configuration.groupsHeads, configuration.groupsHeadsCount * sizeof(int));
//				this->AddMemoryOperation("host - h_clusterGroupHeads", _msize(set->h_clusterGroupHeads));
//			}
//			set->clusterGroupHeadsCount = configuration.groupsHeadsCount;
//
//
//
//
//			set->h_configEgsHeads = (mgpu::byte*)malloc(sizeof(mgpu::byte) * configuration.esgHeadsCount);
//			memcpy(set->h_configEgsHeads, configuration.esgHeads, configuration.esgHeadsCount * sizeof(mgpu::byte));
//			set->h_configEsgHeadsCount = configuration.esgHeadsCount;
//
//			this->AddMemoryOperation("host - h_configEgsHeads", _msize(set->h_configEgsHeads));
//
//			set->h_configDisjunctClustersHeads = (mgpu::byte*)malloc(sizeof(mgpu::byte) * configuration.disjunctClustersHeadsCount);
//			memcpy(set->h_configDisjunctClustersHeads, configuration.disjunctClustersHeads, configuration.disjunctClustersHeadsCount * sizeof(mgpu::byte));
//			set->h_configDisjunctClustersHeadsCount = configuration.disjunctClustersHeadsCount;
//
//			this->AddMemoryOperation("host - h_configDisjunctClustersHeads", _msize(set->h_configEgsHeads));
//
//
//
//			set->h_configDisjunctClustersMap = (mgpu::byte*)malloc(sizeof(mgpu::byte) * configuration.disjunctClustersMapCount);
//			memcpy(set->h_configDisjunctClustersMap, configuration.disjunctClustersMap, configuration.disjunctClustersMapCount * sizeof(mgpu::byte));
//			set->h_configDisjunctClustersMapCount = configuration.disjunctClustersMapCount;
//			this->AddMemoryOperation("host - h_configDisjunctClustersMap", _msize(set->h_configDisjunctClustersMap));
//
//			set->indicatorsCount = configuration.indicatorsCount;
//			set->CLUSTERS_COUNT = configuration.CLUSTERS_COUNT;
//			set->DISJUNCT_CLUSTERS_COUNT = configuration.DISJUNCT_CLUSTERS_COUNT;
//		}
//
//		if (returnStatus.esgError != esgSuccess)
//		{
//			CleanSet(set);
//			delete set;
//			return returnStatus;
//		}
//
//		sets->push_back(std::make_tuple(configuration.setId, set));
//
//		return esgSuccess;
//	}
//
//	operation_errors_t CudaComputeContext::SetIndicators(int setId, int companiesCount, int indicatorsCount, float *indicatorScores) {
//		cudaGetLastError(); //reset errors;
//
//		if (indicatorScores == NULL || indicatorScores <= 0 || companiesCount <= 0)
//			return operation_errors_t(esgInvalidParameters);
//
//		ESGSet* set = GetSet(setId);
//
//		if (set == NULL)
//			return operation_errors_t(esgSetNotFound);
//
//		if (set->companiesCount != companiesCount)
//			return operation_errors_t(esgParametersMismatch);
//
//		if (set->indicatorsCount != indicatorsCount)
//			return operation_errors_t(esgParametersMismatch);
//
//		int matrixElementCount = companiesCount * indicatorsCount;
//
//		float* d_indicators = NULL;
//
//		operation_errors_t returnStatus = operation_errors_t::success();
//
//		for (int i = 0; i < 1; i++)
//		{
//
//			cudaError_t cudaStatus = cudaMalloc((void **)&d_indicators, matrixElementCount * sizeof(float));
//
//			this->AddMemoryOperation("cuda - indicators", matrixElementCount * sizeof(float));
//
//
//			if (cudaStatus != cudaSuccess)
//			{
//				returnStatus = getOperationErrorFromCudaStatusMacro(cudaStatus);
//				break;
//			}
//
//			cudaStatus = cudaMemcpy(d_indicators, indicatorScores, matrixElementCount *sizeof(float), cudaMemcpyHostToDevice);
//			if (cudaStatus != cudaSuccess)
//			{
//				returnStatus = getOperationErrorFromCudaStatusMacro(cudaStatus);
//				break;
//			}
//
//		}
//
//		if (returnStatus.esgError != esgSuccess)
//		{
//			if (d_indicators != NULL) {
//				cudaFree(d_indicators);
//			}
//
//			return returnStatus;
//		}
//
//		float * previous = set->indicators_scores;
//		if (previous != NULL)
//		{
//			cudaFree(previous);
//			//returnOnErrorMacro(cudaStatus);//do nothing if error
//		}
//
//
//		set->indicators_scores = d_indicators;
//
//		return esgSuccess;
//
//	}
//
//	cudaEsg_errors_t CudaComputeContext::CleanSet(ESGSet* set)  {
//
//		if (set == NULL)
//			return esgSuccess;
//
//		if (set->indicators_scores != NULL){
//			cudaFree(set->indicators_scores);
//			set->indicators_scores = NULL;
//		}
//
//		if (set->d_groupHeads != NULL){
//			cudaFree(set->d_groupHeads);
//			set->d_groupHeads = NULL;
//		}
//
//		if (set->attributes != NULL){
//			cudaFree(set->attributes);
//			set->attributes = NULL;
//		}
//
//		if (set->universes != NULL){
//			vector<tuple<int, unsigned char*>> *universes = set->universes;
//			while (!universes->empty()){
//				cudaFree(std::get<1>(universes->back()));
//				universes->pop_back();
//			}
//
//			set->universes = NULL;
//			delete universes;
//		}
//
//		if (set->weightsMatrices != NULL){
//			vector<tuple<int, float*>> *weightsMatrices = set->weightsMatrices;
//			while (!weightsMatrices->empty()){
//				cudaFree(std::get<1>(weightsMatrices->back()));
//				weightsMatrices->pop_back();
//			}
//
//			set->weightsMatrices = NULL;
//			delete weightsMatrices;
//		}
//
//		return esgSuccess;
//	}
//
//	operation_errors_t CudaComputeContext::AddUniverse(int setId, int universeId, int companiesCount, unsigned char * universe)  {
//
//		cudaGetLastError(); //reset errors;
//		if (companiesCount <= 0 || universe == NULL)
//			return operation_errors_t(esgInvalidParameters);
//
//		ESGSet* set = GetSet(setId);
//
//		if (set == NULL)
//			return operation_errors_t(esgSetNotFound);
//
//		if (companiesCount != (set->companiesCount))
//			return operation_errors_t(esgParametersMismatch);
//
//		if (set->GetUniverse(universeId) != NULL)
//			return operation_errors_t(esgDuplicateEntity);
//
//		unsigned char* d_universe = NULL;
//
//
//
//
//
//		cudaError_t cudaStatus = cudaMalloc((void **)&d_universe, companiesCount * sizeof(unsigned char));
//
//		this->AddMemoryOperation("cuda - universe", companiesCount * sizeof(unsigned char));
//
//		returnOnErrorMacro(cudaStatus);
//
//		cudaStatus = cudaMemcpy(d_universe, universe, companiesCount *sizeof(char), cudaMemcpyHostToDevice);
//
//
//		if (cudaStatus != cudaSuccess)
//		{
//			cudaFree(d_universe);
//			returnOnErrorMacro(cudaStatus);
//		}
//
//		set->AddUniverse(universeId, d_universe);
//
//		return operation_errors_t::success();
//	}
//
//	operation_errors_t CudaComputeContext::SetAttributes(int setId, int companiesCount, unsigned char * attributes)  {
//		cudaGetLastError(); //reset errors;
//
//		if (companiesCount <= 0 || attributes == NULL)
//			return esgInvalidParameters;
//
//		ESGSet* set = GetSet(setId);
//
//		if (set == NULL)
//			return operation_errors_t(esgSetNotFound);
//
//		if (set->companiesCount != companiesCount)
//			return operation_errors_t(esgInvalidParameters);
//
//		unsigned char* d_attributes = NULL;
//
//		cudaError_t cudaStatus = cudaMalloc((void **)&d_attributes, companiesCount * sizeof(unsigned char));
//		returnOnErrorMacro(cudaStatus);
//
//		cudaStatus = cudaMemcpy(d_attributes, attributes, companiesCount *sizeof(char), cudaMemcpyHostToDevice);
//		if (cudaStatus != cudaSuccess)
//		{
//			cudaFree(attributes);
//			returnOnErrorMacro(cudaStatus);
//		}
//
//		unsigned char * previousAttributes = set->attributes;
//		set->attributes = d_attributes;
//
//		if (previousAttributes != NULL)
//		{
//			cudaStatus = cudaFree(previousAttributes);
//			//returnOnErrorMacro(cudaStatus);//do nothing if error
//		}
//
//		return esgSuccess;
//	}
//
//	operation_errors_t CudaComputeContext::AddMatrix(int setId, int matrixId, int elementsCount, float * weightsMatrix){
//		cudaGetLastError(); //reset errors;
//		if (elementsCount <= 0 || weightsMatrix == NULL)
//			return operation_errors_t(esgInvalidParameters);
//
//		ESGSet* set = GetSet(setId);
//
//		if (set == NULL)
//			return operation_errors_t(esgSetNotFound);
//
//		if (elementsCount != (set->companiesCount) * (set->indicatorsCount))
//			return operation_errors_t(esgParametersMismatch);
//
//		if (set->GetMatrix(matrixId) != NULL)
//			return operation_errors_t(esgDuplicateEntity);
//
//		float* d_matrix = NULL;
//
//		cudaError_t cudaStatus = cudaMalloc((void **)&d_matrix, elementsCount * sizeof(float));
//
//		this->AddMemoryOperation("cuda - matrix", elementsCount * sizeof(float));
//		returnOnErrorMacro(cudaStatus);
//
//		cudaStatus = cudaMemcpy(d_matrix, weightsMatrix, elementsCount *sizeof(float), cudaMemcpyHostToDevice);
//		if (cudaStatus != cudaSuccess)
//		{
//			cudaFree(d_matrix);
//			returnOnErrorMacro(cudaStatus);
//		}
//
//		set->AddMatrix(matrixId, d_matrix);
//
//		return operation_errors_t::success();
//	}
//
//	operation_errors_t CudaComputeContext::DeleteSet(int setId) {
//		return operation_errors_t(esgNotImplemented);
//	}
//
//	operation_errors_t CudaComputeContext::FillSetAttributes(int setId, int &companiesCount, int &indicatorsCount, int &clusterGroupsCount, int &clustersCount){
//		ESGSet* set = GetSet(setId);
//
//		if (set == NULL)
//			return operation_errors_t(esgSetNotFound);
//
//		companiesCount = set->companiesCount;
//		indicatorsCount = set->indicatorsCount;
//		clusterGroupsCount = set->clusterGroupHeadsCount + 1;
//		clustersCount = set->CLUSTERS_COUNT;
//
//		return operation_errors_t::success();
//	}
//
//	void CudaComputeContext::AddMemoryOperation(std::string name, double elapsedSeconds)
//	{
//		memoryStatistics->operationsList->push_back(make_unique<MemoryOperation>(name, elapsedSeconds));
//	}
//
//	operation_errors_t CudaComputeContext::ResetStatistics()
//	{
//		if (memoryStatistics == NULL)
//			return esgSuccess;
//
//		if (memoryStatistics->operationsList != NULL){
//			memoryStatistics->operationsList.reset(new std::vector<std::unique_ptr<MemoryOperation>>);
//		}
//		return operation_errors_t::success();
//	}
//
//}
